import {axios} from 'taro-axios'
import type {AxiosInstance, AxiosRequestConfig, AxiosResponse} from 'taro-axios'
import Taro from "@tarojs/taro";
import basic from "@/api/basic";

interface RequestConfig extends AxiosRequestConfig {
  // 可以扩展自定义配置
  showLoading?: boolean
  needAuth?: boolean
  returnFormat?: 'raw' | 'data' | 'all'
}

class HttpClient {
  private instance: AxiosInstance
  private static _instance: HttpClient

  /**
   * 获取单例实例
   */
  public static getInstance() {
    if (!this._instance) {
      this._instance = new HttpClient()
    }
    return this._instance
  }

  constructor() {
    // 创建axios实例
    this.instance = axios.create({
      baseURL: basic().getBaseUrl(), // 你的API基础地址
      timeout: 10000, // 请求超时时间
      headers: {
        'Content-Type': 'application/json'
      }
    })

    // 添加请求拦截器
    this.instance.interceptors.request.use((config: RequestConfig) => {
        // 在发送请求之前做些什么
        console.log('请求拦截:', config)

        // 添加token等认证信息
        const token = 'your-token' // 这里可以从store或storage获取
        if (token) {
          config.headers!['Authorization'] = `Bearer ${token}`
        }

        // 如果需要显示loading
        if (config.showLoading) {
          Taro.showLoading({title: '加载中...'})
        }
        return config
      },
      (error) => {
        // 对请求错误做些什么
        return Promise.reject(error)
      }
    )

    // 添加响应拦截器
    this.instance.interceptors.response.use((response: AxiosResponse) => {
        // 对响应数据做点什么
        console.log('响应拦截:', response)

        // 根据配置返回不同格式的数据
        const config = response.config as RequestConfig
        const returnType = config['returnFormat'] || 'data'

        // 隐藏loading
        if (config.showLoading) {
          Taro.hideLoading()
        }

        switch (returnType) {
          case 'raw':
            return response
          case 'data':
            return response.data
          case 'all':
            return {
              data: response.data,
              status: response.status,
              headers: response.headers,
              config: response.config
            }
          default:
            return response.data
        }
      },
      (error) => {
        // 对响应错误做点什么
        console.error('请求错误:', error)

        // 隐藏loading
        if (error.config?.showLoading) {
          Taro.hideLoading()
        }

        // 统一错误处理
        if (error.response) {
          // 服务器返回了错误状态码
          switch (error.response.status) {
            case 401:
              // 处理未授权
              Taro.showToast({title: '未授权，请重新登录', icon: 'none'})
              // 可以跳转到登录页
              break
            case 404:
              Taro.showToast({title: '请求资源不存在', icon: 'none'})
              break
            case 500:
              Taro.showToast({title: '服务器错误', icon: 'none'})
              break
            default:
              Taro.showToast({title: '请求失败', icon: 'none'})
          }
        } else {
          // 请求未发出或网络错误
          Taro.showToast({title: '网络错误，请检查网络连接', icon: 'none'})
        }
        return Promise.reject(error)
      }
    )
  }

  /**
   * GET请求
   * @param url 请求地址
   * @param config 请求配置
   */
  public get<T = any>(url: string, config?: RequestConfig): Promise<T> {
    return this.instance.get(url, config)
  }

  /**
   * POST请求
   * @param url 请求地址
   * @param data 请求数据
   * @param config 请求配置
   */
  public post<T = any>(url: string, data?: any, config?: RequestConfig): Promise<T> {
    return this.instance.post(url, data, config)
  }

  /**
   * PUT请求
   * @param url 请求地址
   * @param data 请求数据
   * @param config 请求配置
   */
  public put<T = any>(url: string, data?: any, config?: RequestConfig): Promise<T> {
    return this.instance.put(url, data, config)
  }

  /**
   * DELETE请求
   * @param url 请求地址
   * @param config 请求配置
   */
  public delete<T = any>(url: string, config?: RequestConfig): Promise<T> {
    return this.instance.delete(url, config)
  }

  /**
   * 通用请求方法
   * @param config 请求配置
   */
  public request<T = any>(config: RequestConfig): Promise<T> {
    return this.instance.request(config)
  }
}

// 导出单例实例
export const httpClient = HttpClient.getInstance()
